package cloud.example.eureka_client.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCommands;
import redis.clients.jedis.JedisPool;

/**
 * @author zjm
 * @date 2018/12/22.
 */
@Component
@Slf4j
public class RedisLockService {
  private static final String SET_IF_NOT_EXIST = "NX";
  private static final String SET_WITH_EXPIRE_TIME = "EX";
  private static final String OKStatus = "OK";

  private final RedisTemplate<Object, Object> redisTemplate;
  private final JedisPool jedisPool;

  public RedisLockService(RedisTemplate<Object, Object> redisTemplate, JedisPool jedisPool) {
    this.redisTemplate = redisTemplate;
    this.jedisPool = jedisPool;
  }

  /*public Boolean lock(String key, String value) {
    Jedis jedis =null;
    String lockKey = "lock:" + key;
    try {
       jedis = jedisPool.getResource();
      String resultCode = jedis.set(lockKey, value, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, EXPIRE_TIME);
      return OKStatus.equals(resultCode) ? Boolean.TRUE : Boolean.FALSE;
//     return redisTemplate.opsForValue().setIfAbsent(lockKey,value);
    }catch (Exception e){
      close(jedis);
      e.printStackTrace();
    }finally {
      returnResource(jedis);
//      redisTemplate.delete(lockKey);
    }
    return false;
  }*/
  public Boolean lock(final String key, final String value, final long expireTime) {
    Assert.isTrue(!StringUtils.isEmpty(key), "key must be not blank");
    String lockKey = "lock:" + key;
    String status = redisTemplate.execute((RedisCallback<String>) connection -> {
      Object nativeConnection = connection.getNativeConnection();
      String result = null;
      if (nativeConnection instanceof JedisCommands) {
        result = ((JedisCommands) nativeConnection).set(lockKey, value, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
      }
      return result;
    });
    return OKStatus.equals(status) ? Boolean.TRUE : Boolean.FALSE;
  }


  public void unLock(String key) {
    String lockKey = "lock:" + key;
    redisTemplate.delete(lockKey);
  }

  private void close(Jedis jedis) {
    if (null != jedis) {
      jedis.close();
    }
  }

  private void returnResource(Jedis jedis) {
    if (null != jedis && null != jedisPool) {
      jedis.close();
    }
  }

  /* @SuppressWarnings("unchecked")
  public Boolean lock(String key, String value) {
    String lockKey = "lock:" + key;
    return redisTemplate.execute((RedisCallback<Boolean>) connection -> {
      byte[] redisKeyBytes = keySerializer().serialize(lockKey);
      byte[] valueBytes = valueSerializer().serialize(value);
      Expiration expiration = Expiration.from(EXPIRE_TIME, TimeUnit.SECONDS);
      connection.set(redisKeyBytes, valueBytes, expiration, RedisStringCommands.SetOption.SET_IF_ABSENT);
      return true;
    });
  }*/
}
